﻿using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace CMS.Controls
{
    public class MyTabControl : TabControl
    {
        #region 私有字段
        private ContextMenuStrip CMS_Main;
        private ToolStripMenuItem TSMI_Refresh;
        private ToolStripMenuItem TSMI_Close;
        private ToolStripMenuItem TSMI_CloseAll;
        #endregion

        public MyTabControl()
        {
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            ItemSize = new Size(180, 30);
            SizeMode = TabSizeMode.Fixed;

            #region 上下文菜单添加
            CMS_Main = new ContextMenuStrip();
            TSMI_Refresh = new ToolStripMenuItem()
            {
                Text = "刷新此页面",
                Image = Resource1.Refresh16,
            };
            TSMI_Refresh.Click += TSMI_Refresh_Click;
            TSMI_Close = new ToolStripMenuItem()
            {
                Text = "关闭此页面",
                Image = Resource1.Close16
            };
            TSMI_Close.Click += TSMI_Close_Click;

            TSMI_CloseAll = new ToolStripMenuItem()
            {
                Text = "关闭所有页面",
                Image = Resource1.Close16
            };
            TSMI_CloseAll.Click += TSMI_CloseAll_Click;

            CMS_Main.Items.AddRange(new ToolStripItem[] { TSMI_Refresh, new ToolStripSeparator(), TSMI_Close, TSMI_CloseAll });
            #endregion
        }



        #region 上下文菜单相关

        /// <summary>
        /// 响应鼠标按下,弹出上下文菜单项
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);
            for (int i = 0; i < TabCount; i++)
            {
                if (GetTabRect(i).Contains(e.Location))
                {
                    SelectedIndex = i;
                }
            }
            if (e.Button == MouseButtons.Right)
            {
                CMS_Main.Show(this, e.Location);
            }
        }

        private void TSMI_Refresh_Click(object sender, EventArgs e)
        {
            if (SelectedTab is LazyTabPage lazy)
            {
                lazy.ReLoadTabPage();
            }
        }

        private void TSMI_Close_Click(object sender, EventArgs e)
        {
            if (SelectedTab is LazyTabPage lazy)
            {
                lazy.CloseTabPage();
            }
        }

        private void TSMI_CloseAll_Click(object sender, EventArgs e)
        {
            foreach (object tab in TabPages)
            {
                if (tab is LazyTabPage lazy)
                {
                    lazy.CloseTabPage();
                }
            }
            Invalidate();
        }


        #endregion


        #region 绘制控件

        /// <summary>
        /// 标题画刷
        /// </summary>
        private static readonly Brush _TabTitleBrush = Brushes.Black;

        /// <summary>
        /// 文字布局方式
        /// </summary>
        private static readonly StringFormat _TabTitleFormat = new StringFormat() { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center };

        /// <summary>
        /// 标签页字体
        /// </summary>
        private static readonly Font _TabTitleFont = new Font("微软雅黑", 14, GraphicsUnit.Pixel);

        /// <summary>
        /// 标签页背景色(已选择时)
        /// </summary>
        private static readonly Brush _TabSelectedBrush = Brushes.White;

        /// <summary>
        /// 标签页背景色(未选择时)
        /// </summary>
        private static readonly Brush _TabNonSelectBrush = Brushes.WhiteSmoke;

        /// <summary>
        /// 标签页背景色(未选择时)
        /// </summary>
        private static readonly Brush _TabNonSelectBrushActive = Brushes.Gainsboro;

        /// <summary>
        /// 外边框画笔
        /// </summary>
        private static readonly Pen _OutLinePen = Pens.LightGray;

        protected override void OnPaint(PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            g.SmoothingMode = SmoothingMode.AntiAlias;  //使绘图质量最高，即消除锯齿
            g.Clear(Color.White);
            Rectangle r = DisplayRectangle;
            r.Offset(-1, -1);
            r.Width += 1;
            r.Height += 1;
            g.DrawRectangle(_OutLinePen, r);
            for (int i = 0; i < TabPages.Count; i++)
            {
                _DrawItem(g, i);
            }
        }

        /// <summary>
        /// 标签的圆角半径
        /// </summary>
        private const int _Radius = 3;

        private void _DrawItem(Graphics g, int index)
        {
            Rectangle backRect = GetTabRect(index);
            TabPage item = TabPages[index];
            Brush nonSelectBrush;
            if (item is LazyTabPage tab)
            {
                nonSelectBrush = tab.IsCreate ? _TabNonSelectBrushActive : _TabNonSelectBrush;
            }
            else
            {
                nonSelectBrush = _TabNonSelectBrush;
            }
            switch (Alignment)
            {
                case TabAlignment.Top:
                    backRect.X += 1;
                    backRect.Y += 2;
                    backRect.Width -= 3;
                    if (SelectedTab == item)
                    {
                        GraphicsPath path = GenTabPath(backRect, _Radius, Alignment);
                        g.FillPath(_TabSelectedBrush, path);
                        g.DrawPath(_OutLinePen, path);
                    }
                    else
                    {
                        backRect.Height -= 4;
                        GraphicsPath path = GenTabPath(backRect, _Radius, Alignment);
                        g.FillPath(nonSelectBrush, path);
                        path.CloseFigure();
                        g.DrawPath(_OutLinePen, path);
                    }
                    break;
                case TabAlignment.Bottom:
                    backRect.X += 1;
                    backRect.Y -= 2;
                    backRect.Width -= 3;
                    if (SelectedTab == item)
                    {
                        GraphicsPath path = GenTabPath(backRect, _Radius, Alignment);
                        g.FillPath(_TabSelectedBrush, path);
                        g.DrawPath(_OutLinePen, path);
                    }
                    else
                    {
                        backRect.Y += 4;
                        backRect.Height -= 4;
                        GraphicsPath path = GenTabPath(backRect, _Radius, Alignment);
                        g.FillPath(nonSelectBrush, path);
                        path.CloseFigure();
                        g.DrawPath(_OutLinePen, path);
                    }
                    break;
                case TabAlignment.Left:
                    backRect.X += 1;
                    backRect.Y += 1;
                    backRect.Width++;
                    backRect.Height -= 3;

                    if (SelectedTab == item)
                    {
                        GraphicsPath path = GenTabPath(backRect, _Radius, Alignment);
                        g.FillPath(_TabSelectedBrush, path);
                        g.DrawPath(_OutLinePen, path);
                    }
                    else
                    {
                        backRect.Width -= 4;
                        GraphicsPath path = GenTabPath(backRect, _Radius, Alignment);
                        g.FillPath(nonSelectBrush, path);
                        path.CloseFigure();
                        g.DrawPath(_OutLinePen, path);
                    }
                    break;
                case TabAlignment.Right:
                    backRect.X -= 2;
                    backRect.Y += 1;
                    backRect.Width += 3;
                    backRect.Height -= 3;

                    if (SelectedTab == item)
                    {
                        GraphicsPath path = GenTabPath(backRect, _Radius, Alignment);
                        g.FillPath(_TabSelectedBrush, path);
                        g.DrawPath(_OutLinePen, path);
                    }
                    else
                    {
                        backRect.X += 3;
                        backRect.Width -= 3;
                        GraphicsPath path = GenTabPath(backRect, _Radius, Alignment);
                        g.FillPath(nonSelectBrush, path);
                        path.CloseFigure();
                        g.DrawPath(_OutLinePen, path);
                    }
                    break;
            }

            g.DrawString(item.Text, _TabTitleFont, _TabTitleBrush, GetTabRect(index), _TabTitleFormat);
        }

        private GraphicsPath GenTabPath(Rectangle rect, int radius, TabAlignment alignment)
        {
            GraphicsPath path = new GraphicsPath();
            int r2 = radius * 2;

            switch (alignment)
            {
                case TabAlignment.Top:
                    path.AddLine(rect.Left, rect.Bottom, rect.Left, rect.Top + radius);
                    path.AddArc(rect.Left, rect.Top, r2, r2, 180, 90);
                    path.AddLine(rect.Left + radius, rect.Top, rect.Right - radius, rect.Top);
                    path.AddArc(rect.Right - r2, rect.Top, r2, r2, 270, 90);
                    path.AddLine(rect.Right, rect.Top + radius, rect.Right, rect.Bottom);
                    break;
                case TabAlignment.Left:
                    path.AddLine(rect.Right, rect.Bottom, rect.Left + radius, rect.Bottom);
                    path.AddArc(rect.Left, rect.Bottom - r2, r2, r2, 90, 90);
                    path.AddLine(rect.Left, rect.Bottom - radius, rect.Left, rect.Top + radius);
                    path.AddArc(rect.Left, rect.Top, r2, r2, 180, 90);
                    path.AddLine(rect.Left + radius, rect.Top, rect.Right, rect.Top);
                    break;
                case TabAlignment.Right:
                    path.AddLine(rect.Left, rect.Top, rect.Right - radius, rect.Top);
                    path.AddArc(rect.Right - r2, rect.Top, r2, r2, 270, 90);
                    path.AddLine(rect.Right, rect.Top + radius, rect.Right, rect.Bottom - radius);
                    path.AddArc(rect.Right - r2, rect.Bottom - r2, r2, r2, 0, 90);
                    path.AddLine(rect.Right - radius, rect.Bottom, rect.Left, rect.Bottom);
                    break;
                case TabAlignment.Bottom:
                    path.AddLine(rect.Right, rect.Top, rect.Right, rect.Bottom - radius);
                    path.AddArc(rect.Right - r2, rect.Bottom - r2, r2, r2, 0, 90);
                    path.AddLine(rect.Right - radius, rect.Bottom, rect.Left + radius, rect.Bottom);
                    path.AddArc(rect.Left, rect.Bottom - r2, r2, r2, 90, 90);
                    path.AddLine(rect.Left, rect.Bottom - radius, rect.Left, rect.Top);
                    break;
            }
            return path;
        }

        protected override void OnSelectedIndexChanged(EventArgs e)
        {
            base.OnSelectedIndexChanged(e);
            if (SelectedTab is LazyTabPage lazy)
            {
                lazy.ActiveTabPage();
            }
        }

        protected override void OnControlAdded(ControlEventArgs e)
        {
            base.OnControlAdded(e);
            if (TabPages.Count == 1)
            {
                if (SelectedTab is LazyTabPage lazy)
                {
                    lazy.ActiveTabPage();
                }
            }
        }


        #endregion

    }
}
